Time Series

#head(filteredchange)
filteredchange %>%
  ggplot(aes(x = year, y = pf_ss, group = countries)) +
  geom_line(alpha = 0.2, size = 0.1) +
  labs(title = "Countries with the Largest Positive Change in Safety and Security in Any Given Year",
       x = "Year",
       y = "Saftey and Security Score") +
  theme_light() +
  geom_line(data = subset(filteredchange, countries %in% inc_ss), aes(color = countries), size = 1.5, alpha = 0.7)

#filteredchange %>% filter(countries %in% inc_ss, year == 2016) %>% group_by(region) %>% summarize(mean = mean(pf_ss), n = n())
filteredchange %>%
  ggplot(aes(x = year, y = pf_ss, group = countries)) +
  geom_line(alpha = 0.2, size = 0.1) +
  labs(title = "Countries with the Largest Negative Change in Safety and Security in Any Given Year",
       x = "Year",
       y = "Saftey and Security Score") +
  theme_light() +
  geom_line(data = subset(filteredchange, countries %in% dec_ss), aes(color = countries), size = 1.5, alpha = 0.7)

#filteredchange %>% filter(countries %in% dec_ss, year == 2016) %>% group_by(region) %>% summarize(mean = mean(pf_ss), n = n())
filteredchange %>%
  ggplot(aes(x = year, y = pf_ss_women, group = countries)) +
  geom_line(alpha = 0.2, size = 0.1) +
  labs(title = "Countries with the Largest Positive Change in Women's Safety and Security in Any Given Year",
       x = "Year",
       y = "Women's Saftey and Security Score") +
  theme_light() +
  geom_line(data = subset(filteredchange, countries %in% inc_ss_women), aes(color = countries), size = 1.5, alpha = 0.7)

filteredchange %>%
  ggplot(aes(x = year, y = pf_ss_women, group = countries)) +
  geom_line(alpha = 0.2, size = 0.1) +
  labs(title = "Countries with the Largest Negative Change in Women's Safety and Security in Any Given Year",
       x = "Year",
       y = "Women's Saftey and Security Score") +
  theme_light() +
  geom_line(data = subset(filteredchange, countries %in% dec_ss_women), aes(color = countries), size = 1.5, alpha = 0.7)

data_by_year %>%
  ggplot(aes(x = year, y = avg_pf_ss, group = region)) +
  geom_line(aes(color = region), size = 1.25, alpha = 0.5) +
  labs(title = "Average Safety and Security by Region", x = "Year", y = "Safety and Security Score", fill = "Region") +
  scale_y_continuous(breaks = seq(6,10,0.5)) +
  theme_light() 

data_by_year %>%
  ggplot(aes(x = year, y = avg_pf_ss_women, group = region)) +
  geom_line(aes(color = region), size = 1.25, alpha = 0.5) +
  labs(title = "Average Safety and Security of Women by Region", x = "Year", y = "Safety and Security Score", fill = "Region") +
  scale_y_continuous(breaks = seq(6,10,0.5)) +
  theme_light()

data_by_year %>%
  filter(year == 2016, region %in% c("North America", "Western Europe", "Eastern Europe", "Latin America & the Caribbean")) %>%
  select(region, avg_pf_ss, avg_pf_ss_women) %>% melt %>%
  ggplot(aes(region, value, fill = variable)) + geom_bar(stat = "identity", position = "dodge") +
  labs(x = "Region", y = "Safety and Security Score", title = "2016 Overall and Women's Safety and Security By Region (Western Hemisphere)", fill = "Variable") + scale_fill_manual(labels = c("Average Overall Security", "Average Women's Security"), values = c("Red", "Blue"))
Using region as id variables

data_by_year %>%
  filter(year == 2016, region %in% c("South Asia", "Oceania", "East Asia", "Caucasus & Central Asia", "Middle East & North Africa", "Sub-Saharan Africa")) %>%
  select(region, avg_pf_ss, avg_pf_ss_women) %>% melt %>%
  ggplot(aes(region, value, fill = variable)) + geom_bar(stat = "identity", position = "dodge") +
  labs(x = "Region", y = "Safety and Security Score", title = "2016 Overall and Women's Safety and Security By Region (Eastern Hemishpere)", fill = "Variable") + scale_fill_manual(labels = c("Average Overall Security", "Average Women's Security"), values = c("Red", "Blue"))
Using region as id variables

#unique(data_by_year$region)
  
ggplot(data = hfi16, aes(x = pf_score, y = ef_score)) + 
  geom_point(aes(col = pf_ss_women)) +
  labs(x = "Personal Freedom Score", y = "Economic Freedom Score", main = "Personal and Economic Freedom and Women Security", color = "Security of Women")

# light grey boundaries
l <- list(color = toRGB("grey"), width = 0.9)
# specify map projection/options
g <- list(
showframe = FALSE,
showcoastlines = FALSE,
projection = list(type = 'Mercator')
)
plot_geo(score16) %>%
add_trace(
z = ~ round(hf_score, 2), color = ~hf_score, colors = 'Blues', 
text = ~countries, locations = ~ISO_code, marker = list(line = l)) %>%
colorbar(title = 'Human Freedom \nScore, 2016') %>%
layout(
title = 'Human Freedom Score, 2016',
geo = g
)
l <- list(color = toRGB("grey"), width = 0.9)
# specify map projection/options
g <- list(
showframe = FALSE,
showcoastlines = FALSE,
projection = list(type = 'Mercator')
)
plot_geo(score08) %>%
add_trace(
z = ~ round(hf_score, 2), color = ~hf_score, colors = 'Blues', 
text = ~countries, locations = ~ISO_code, marker = list(line = l)) %>%
colorbar(title = 'Human Freedom \nScore, 2008') %>%
layout(
title = 'Human Freedom Score, 2008',
geo = g
)
ggplotchange <- ggplot(data = map.world.change, aes(x = long, y = lat, group= group, fill = human_freedom_score, text =  paste("country:", region, "<br>", "personal_freedom_score:", personal_freedom_score, "<br>", "personal_freedom_rank:", personal_freedom_rank, "<br>", "economy_freedom_score:", economy_freedom_score, "<br>", "economy_freedom_rank:", economy_freedom_rank, "<br>", "human_freedom_score:", human_freedom_score, "<br>", "human_freedom_rank:", human_freedom_rank))) +
  geom_polygon() +
  scale_fill_gradient2(low = "#383C46", high = "#D4DBEA", mid="#5A76AF", name="Change of \nFreedom Score") +
  theme(panel.background =  element_rect(fill = "white", colour = "grey50"),
        panel.grid = element_blank(),
        axis.text = element_blank(),
        axis.title = element_blank(),
        axis.ticks = element_blank(),
        legend.justification = "top",
        plot.title = element_text(hjust = 0.5)) +
  labs(title = "Changes from 2008 to 2016") #+
  #guides(fill = guide_legend(title=NULL))
ggplotly(ggplotchange, tooltip = c("text"))
str(score16)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   162 obs. of  9 variables:
 $ ISO_code : chr  "ALB" "DZA" "AGO" "ARG" ...
 $ countries: chr  "Albania" "Algeria" "Angola" "Argentina" ...
 $ region   : chr  "Eastern Europe" "Middle East & North Africa" "Sub-Saharan Africa" "Latin America & the Caribbean" ...
 $ pf_score : num  7.6 5.28 6.11 8.1 6.91 ...
 $ pf_rank  : num  57 147 117 42 84 11 8 131 64 114 ...
 $ ef_score : num  7.54 4.99 5.17 4.84 7.57 7.98 7.58 6.49 7.34 7.56 ...
 $ ef_rank  : num  34 159 155 160 29 10 27 106 49 30 ...
 $ hf_score : num  7.57 5.14 5.64 6.47 7.24 ...
 $ hf_rank  : num  48 155 142 107 57 4 16 130 50 75 ...
p <- ggplot(score16, aes(x=hf_score ,y=reorder(countries,hf_rank))) + 
  geom_point(colour = "red", alpha = .5) + 
  geom_segment(aes(yend=reorder(countries,hf_rank)), xend = 0, colour="pink", alpha = .5) + 
  theme(axis.text.y = element_text(angle = 0, hjust = 1)) + 
  labs(title = "World Human Freedom Rank in 2016", y = "Country Name", x = "Human Freedom Rank")
ggplotly(p)
score = hfi %>% filter(year == 2016) %>% select(pf_ss_women, ISO_code, countries, region, pf_score, pf_rank, ef_score, ef_rank, hf_score, hf_rank) %>%  na.omit()
p1 =ggplot(score, aes(x = ef_score, y = pf_score, color = region), group = countries)
pointsToLabel <- c("Russia", "Venezuela", "Iraq", "Myanmar", "Sudan",
                   "Afghanistan", "Congo", "Greece", "Argentina", "Brazil",
                   "India", "Italy", "China", "South Africa", "Spain",
                   "Botswana", "Cape Verde", "Bhutan", "Rwanda", "France",
                   "United States", "Germany", "Britain", "Barbados", "Norway", "Japan",
                   "New Zealand", "Singapore")
mR2 <- summary(lm(pf_score ~ 1 + ef_score , data = score))$r.squared
mR2 <- paste0(format(mR2, digits = 2))
p2 = p1 + geom_smooth(mapping = aes(linetype = "r2"),
              method = "lm",se = FALSE,
              color = "red") + # geom_point(size = 2, stroke = 1.25) +
  geom_point(aes(size = round(pf_ss_women)), alpha = 0.6)+ labs(size = "Women Security Score") + 
  geom_text_repel(aes(label = countries) , color = "black", size = 2.5, data = filter(score, countries %in% pointsToLabel), force = 2 ) + #check_overlap = TRUE
  scale_x_continuous(name = "Economic Freedom Score, 2016 (10 = Most Free)", limits = c(2.5,9.5), breaks = 2.5:9.5) +
  scale_y_continuous(name = "Personal Freedom Score, 2016 (10 = Most Free)", limits = c(2.5,9.5), breaks = 2.5:9.5) +
  scale_color_brewer(name = "" , type = 'div', palette = 'Spectral') +
  scale_linetype(name = "",
                 breaks = "r2",
                 labels = list(bquote(R^2==.(mR2))),
                 guide = guide_legend(override.aes = list(linetype = 1, size = 2, color = "red"), order=2)) +
  ggtitle("Economic & Personal Freedom and Women Security 2016") +
  theme_minimal() + # start with a minimal theme and add what we need
  theme(text = element_text(color = "gray20"),
        legend.text = element_text(size = 10, color = "gray10"),
        axis.text = element_text(face = "italic"),
        axis.title.x = element_text(vjust = -1), # move title away from axis
        axis.title.y = element_text(vjust = 2), # move away for axis
        axis.ticks.y = element_blank(), # element_blank() is how we remove elements
        axis.line = element_line(color = "gray40", size = 0.3),
        #panel.grid.major = element_blank()
        #axis.line.y = element_blank()
        panel.grid.major = element_line(color = "gray", size = 0.2)
        #panel.grid.major.x = element_blank()
        )
  
suppressWarnings(print(p2))

df = hfi %>% filter(year == 2008) %>% select(year, ISO_code, countries, region, starts_with('pf_'))
df=df[,colSums(is.na(df))<nrow(df)]
df = df %>% na.omit()
cormat <- round(cor(df[,5:57]),2)
#
get_lower_tri<-function(cormat){
  cormat[upper.tri(cormat)] <- NA
  return(cormat)
}
get_upper_tri <- function(cormat){
  cormat[lower.tri(cormat)]<- NA
  return(cormat)
}
reorder_cormat <- function(cormat){
  # Use correlation between variables as distance
  dd <- as.dist((1-cormat)/2) 
  hc <- hclust(dd)
  cormat <-cormat[hc$order, hc$order]
}
cormat <- reorder_cormat(cormat)
upper_tri <- get_upper_tri(cormat)
# Melt the correlation matrix
melted_cormat <- melt(upper_tri, na.rm = TRUE)
# Create a ggheatmap
ggheatmap <- ggplot(melted_cormat, aes(Var2, Var1, fill = value))+
  geom_tile(color = "white")+
  scale_fill_gradient2(low = "blue", high = "red", mid = "white", 
                       midpoint = 0, limit = c(-1,1), space = "Lab", 
                       name="Pearson\nCorrelation") +
  theme_minimal()+ # minimal theme
  theme(axis.text.x = element_text(angle = 45, vjust = 1, 
                                   size = 8.5, hjust = 1), 
        panel.grid.major = element_line(color = "gray", size = 0.2)) +
  coord_fixed()
ggheatmap + 
  theme(
    axis.title.x = element_blank(),
    axis.title.y = element_blank(),
    panel.grid.major = element_line(color = "gray", size = 0.2),
    panel.border = element_blank(),
    panel.background = element_blank(),
    axis.ticks = element_blank()
    ) + ggtitle("Personal Freedom, 2008")

hfi16 = hfi[hfi$year == 2016,]
hfi16 <- hfi16 %>% select(year, X1 = countries, region, pf_ss, pf_rol, pf_religion, pf_association, pf_identity, pf_expression, pf_score, pf_movement, ef_government, ef_legal, ef_score, ef_regulation, ef_money, ef_trade, contains("women"), pf_identity_sex_female, pf_identity_divorce)
hfi16 <- hfi16[-which(is.na(hfi16[4:26])),] %>% na.omit()
set.seed(1235) 
clusters <- hfi16 %>% select(contains("women")) %>% na.omit()
k3 <- kmeans(clusters, 3)
k3
K-means clustering with 3 clusters of sizes 48, 26, 58

Cluster means:
  pf_ss_women_fgm pf_ss_women_missing pf_ss_women_inheritance_widows pf_ss_women_inheritance_daughters
1        9.018750            9.010417                      5.3125000                         5.1041667
2        8.684615            7.884615                      0.1923077                         0.1923077
3       10.000000            9.655172                      9.7413793                         9.9137931
  pf_ss_women_inheritance pf_ss_women pf_movement_women
1               5.2083333    7.745833          7.812500
2               0.1923077    5.587179          3.653846
3               9.8275862    9.827586          9.568966

Clustering vector:
  [1] 1 2 1 3 3 3 3 1 2 2 3 3 1 1 1 1 3 1 2 3 1 3 1 2 1 1 3 1 3 1 3 3 3 3 3 3 2 3 3 1 3 3 1 1 3 1 1 3 1 1 1 3 3 3 1 1 2 2
 [59] 3 3 3 3 3 2 3 1 3 2 1 3 2 2 3 3 1 1 2 1 2 1 1 1 3 2 1 2 1 3 3 3 1 2 2 3 2 2 3 1 1 1 3 3 2 3 3 1 2 1 3 1 3 3 3 3 1 2
[117] 3 3 1 2 1 1 2 3 1 3 2 3 3 1 3 1

Within cluster sum of squares by cluster:
[1] 902.7201 557.8034 298.1801
 (between_SS / total_SS =  78.2 %)

Available components:

[1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss" "betweenss"    "size"        
[8] "iter"         "ifault"      
fviz_cluster(k3, data = clusters)

fviz_nbclust(clusters, kmeans, method = "wss")

hfi16$clusters <- as.factor(k3$cluster)
hfi16$regionf <- factor(hfi16$region)
corr <- round(cor(na.omit(hfi16[4:26])), 1)
ggcorrplot(corr, hc.order = TRUE, method = "circle", lab = TRUE, lab_size = 3)

hfi16 <- hfi16 %>%
  group_by(clusters) %>%
  mutate(clusteravgwss = mean(pf_ss_women), clustersdwss = sd(pf_ss_women), clusteravgss = mean(pf_ss), clustersdss = sd(pf_ss))
ggplot(data = hfi16, aes(y = pf_ss_women, x = pf_religion)) +
  scale_shape_manual(values = 1:nlevels(hfi16$regionf)) +
  geom_jitter(aes(color = clusters, shape = regionf)) +
  labs(col = "Clusters",
       shape = "Regions",
       x = "Religious Freedom",
       y = "Security of Women") +
  geom_text_repel(
    data = subset(hfi16, pf_ss_women  < (clusteravgwss - clustersdwss)),
    aes(
      x = pf_religion,
      y = pf_ss_women,
      label = X1,
      color =
        clusters
    ),
    nudge_y = .5
  )

ggplot(data = hfi16, aes(y = pf_ss_women, x = pf_rol)) +
  scale_shape_manual(values = 1:nlevels(hfi16$regionf)) +
  geom_jitter(aes(color = clusters, shape = regionf)) +
  labs(col = "Clusters",
       shape = "Regions",
       x = "Rule of Law",
       y = "Security of Women") +
  geom_text_repel(
    data = subset(hfi16, pf_ss_women  < (clusteravgwss - clustersdwss)),
    aes(
      x = pf_rol,
      y = pf_ss_women,
      label = X1,
      color =
        clusters
    ),
    nudge_y = .5
  )

ggplot(data = hfi16, aes(y = pf_ss_women, x = ef_score)) +
  scale_shape_manual(values = 1:nlevels(hfi16$regionf)) +
  geom_jitter(aes(color = clusters, shape = regionf)) +
  labs(col = "Clusters",
       shape = "Regions",
       x = "Economic Freedom Score",
       y = "Security of Women") +
  geom_text_repel(
    data = subset(hfi16, pf_ss_women  < (clusteravgwss - clustersdwss)),
    aes(
      x = ef_score,
      y = pf_ss_women,
      label = X1,
      color =
        clusters
    ),
    nudge_y = .5
  )

ggplot(data = hfi16, aes(y = pf_ss_women, x = ef_money)) +
  scale_shape_manual(values = 1:nlevels(hfi16$regionf)) +
  geom_jitter(aes(color = clusters, shape = regionf)) +
  labs(col = "Clusters",
       shape = "Regions",
       x = "Access to Sound Money",
       y = "Security of Women") +
  geom_text_repel(
    data = subset(hfi16, pf_ss_women  < (clusteravgwss - clustersdwss)),
    aes(
      x = ef_money,
      y = pf_ss_women,
      label = X1,
      color =
        clusters
    ),
    nudge_y = .5
  )

ggplot(data = hfi16, aes(y = pf_ss_women, x = pf_identity)) +
  scale_shape_manual(values = 1:nlevels(hfi16$regionf)) +
  geom_jitter(aes(color = clusters, shape = regionf)) +
  labs(col = "Clusters",
       shape = "Regions",
       x = "Access to Divorce",
       y = "Security of Women") +
  geom_text_repel(
    data = subset(hfi16, pf_ss_women  < (clusteravgwss - clustersdwss)),
    aes(
      x = pf_identity,
      y = pf_ss_women,
      label = X1,
      color =
        clusters
    ), nudge_y = .5
  )

ggplot(data = hfi16, aes(y = pf_ss_women, x = pf_score)) +
  scale_shape_manual(values = 1:nlevels(hfi16$regionf)) +
  geom_jitter(aes(color = clusters, shape = regionf)) +
  labs(col = "Clusters",
       shape = "Regions",
       x = "Personal Freedom Score",
       y = "Security of Women") +
  geom_text_repel(
    data = subset(hfi16, pf_ss_women  < (clusteravgwss - clustersdwss)),
    aes(
      x = pf_score,
      y = pf_ss_women,
      label = X1,
      color =
        clusters
    ), nudge_y = .5
  )

ggplot(data = hfi16, aes(y = pf_ss_women, x = pf_ss)) +
  scale_shape_manual(values = 1:nlevels(hfi16$regionf)) +
  geom_jitter(aes(color = clusters, shape = regionf)) +
  labs(col = "Clusters",
       shape = "Regions",
       x = "General Security",
       y = "Security of Women") +
  geom_text_repel(
    data = subset(hfi16, pf_ss  < (clusteravgss - clustersdss)),
    aes(
      x = pf_ss,
      y = pf_ss_women,
      label = X1,
      color =
        clusters
    ), nudge_y = .5
  )

perc <- hfi16 %>% group_by(clusters) %>% mutate(ninclust = n()) %>% ungroup()
perc <- perc %>% group_by(region) %>% mutate(ninregion = n()) %>% ungroup()
hfi16 %>% 
  select(X1,clusters)
# light grey boundaries
l <- list(color = clusters, width = 0.5)
# specify map projection/options
g <- list(
showframe = TRUE,
showcoastlines = TRUE,
scope="world",
projection = list(type = 'Mercator')
)
hfi16$clusters <- as.factor(hfi16$clusters)
plot_geo(hfi16) %>%
add_trace(z = ~clusters,
text = ~X1, locations = ~ISO_code, marker = list(line = l,inherit = TRUE)
) %>%
colorbar(title="") %>% 
layout(
title = 'Women Freedom Clusters World Map',
geo = g
)
Error in eval(expr, data, expr_env) : object 'ISO_code' not found
LS0tDQp0aXRsZTogIjMwLWV4cGxvcmF0aW9uIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyBFeHBsb3JhdGlvbiBvZiBob3cgV2VzdCBSZWdpb25zIHJlbGF0ZWQgdG8gcHJlc29uYWwgYW5kIGVjb21ub21pYyBmcmVlZG9tDQpgYGB7ciBzdW1tYXJ5X3dlc3R9DQpzdW1tYXJ5KGhmaV93ZXN0KQ0KIyBNb250ZW5ncm8gaXMgdGhlIG9ubHkgd2VzdGVybiBjb3VudHJ5IHdpdGhvdXQgZGF0YSBmb3IgdGhlc2UgdmFyYWlibGVzDQpoZmlfd2VzdCA8LSBoZmlfd2VzdFstd2hpY2goaGZpX3dlc3QkeDEgPT0gIk1vbnRlbmVncm8iKSxdDQpjb3IoaGZpX3dlc3RbNToxMl0sIGhmaV93ZXN0JHBlcnNvbmFsX2ZyZWVkb20pDQpgYGANCg0KYGBge3IgcGZfd2VzdH0NCmhmaV93ZXN0ICU+JQ0KICBnZ3Bsb3QoYWVzKHJlZ2lvbiwgcGVyc29uYWxfZnJlZWRvbSkpICsgZ2VvbV9ib3hwbG90KCkNCmBgYA0KDQpgYGB7ciBlZl93ZXN0fQ0KaGZpX3dlc3QgJT4lDQogIGdncGxvdChhZXMocmVnaW9uLCBlY29ub21pY19mcmVlZG9tKSkgKyBnZW9tX2JveHBsb3QoKQ0KYGBgDQoNCg0KIyBUaW1lIFNlcmllcw0KDQpgYGB7ciBsYXJnZXN0X2NoYW5nZX0NCiNoZWFkKGZpbHRlcmVkY2hhbmdlKQ0KDQpmaWx0ZXJlZGNoYW5nZSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IHBmX3NzLCBncm91cCA9IGNvdW50cmllcykpICsNCiAgZ2VvbV9saW5lKGFscGhhID0gMC4yLCBzaXplID0gMC4xKSArDQogIGxhYnModGl0bGUgPSAiQ291bnRyaWVzIHdpdGggdGhlIExhcmdlc3QgUG9zaXRpdmUgQ2hhbmdlIGluIFNhZmV0eSBhbmQgU2VjdXJpdHkgaW4gQW55IEdpdmVuIFllYXIiLA0KICAgICAgIHggPSAiWWVhciIsDQogICAgICAgeSA9ICJTYWZ0ZXkgYW5kIFNlY3VyaXR5IFNjb3JlIikgKw0KICB0aGVtZV9saWdodCgpICsNCiAgZ2VvbV9saW5lKGRhdGEgPSBzdWJzZXQoZmlsdGVyZWRjaGFuZ2UsIGNvdW50cmllcyAlaW4lIGluY19zcyksIGFlcyhjb2xvciA9IGNvdW50cmllcyksIHNpemUgPSAxLjUsIGFscGhhID0gMC43KQ0KDQojZmlsdGVyZWRjaGFuZ2UgJT4lIGZpbHRlcihjb3VudHJpZXMgJWluJSBpbmNfc3MsIHllYXIgPT0gMjAxNikgJT4lIGdyb3VwX2J5KHJlZ2lvbikgJT4lIHN1bW1hcml6ZShtZWFuID0gbWVhbihwZl9zcyksIG4gPSBuKCkpDQoNCmZpbHRlcmVkY2hhbmdlICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gcGZfc3MsIGdyb3VwID0gY291bnRyaWVzKSkgKw0KICBnZW9tX2xpbmUoYWxwaGEgPSAwLjIsIHNpemUgPSAwLjEpICsNCiAgbGFicyh0aXRsZSA9ICJDb3VudHJpZXMgd2l0aCB0aGUgTGFyZ2VzdCBOZWdhdGl2ZSBDaGFuZ2UgaW4gU2FmZXR5IGFuZCBTZWN1cml0eSBpbiBBbnkgR2l2ZW4gWWVhciIsDQogICAgICAgeCA9ICJZZWFyIiwNCiAgICAgICB5ID0gIlNhZnRleSBhbmQgU2VjdXJpdHkgU2NvcmUiKSArDQogIHRoZW1lX2xpZ2h0KCkgKw0KICBnZW9tX2xpbmUoZGF0YSA9IHN1YnNldChmaWx0ZXJlZGNoYW5nZSwgY291bnRyaWVzICVpbiUgZGVjX3NzKSwgYWVzKGNvbG9yID0gY291bnRyaWVzKSwgc2l6ZSA9IDEuNSwgYWxwaGEgPSAwLjcpDQoNCiNmaWx0ZXJlZGNoYW5nZSAlPiUgZmlsdGVyKGNvdW50cmllcyAlaW4lIGRlY19zcywgeWVhciA9PSAyMDE2KSAlPiUgZ3JvdXBfYnkocmVnaW9uKSAlPiUgc3VtbWFyaXplKG1lYW4gPSBtZWFuKHBmX3NzKSwgbiA9IG4oKSkNCg0KZmlsdGVyZWRjaGFuZ2UgJT4lDQogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSBwZl9zc193b21lbiwgZ3JvdXAgPSBjb3VudHJpZXMpKSArDQogIGdlb21fbGluZShhbHBoYSA9IDAuMiwgc2l6ZSA9IDAuMSkgKw0KICBsYWJzKHRpdGxlID0gIkNvdW50cmllcyB3aXRoIHRoZSBMYXJnZXN0IFBvc2l0aXZlIENoYW5nZSBpbiBXb21lbidzIFNhZmV0eSBhbmQgU2VjdXJpdHkgaW4gQW55IEdpdmVuIFllYXIiLA0KICAgICAgIHggPSAiWWVhciIsDQogICAgICAgeSA9ICJXb21lbidzIFNhZnRleSBhbmQgU2VjdXJpdHkgU2NvcmUiKSArDQogIHRoZW1lX2xpZ2h0KCkgKw0KICBnZW9tX2xpbmUoZGF0YSA9IHN1YnNldChmaWx0ZXJlZGNoYW5nZSwgY291bnRyaWVzICVpbiUgaW5jX3NzX3dvbWVuKSwgYWVzKGNvbG9yID0gY291bnRyaWVzKSwgc2l6ZSA9IDEuNSwgYWxwaGEgPSAwLjcpDQoNCmZpbHRlcmVkY2hhbmdlICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gcGZfc3Nfd29tZW4sIGdyb3VwID0gY291bnRyaWVzKSkgKw0KICBnZW9tX2xpbmUoYWxwaGEgPSAwLjIsIHNpemUgPSAwLjEpICsNCiAgbGFicyh0aXRsZSA9ICJDb3VudHJpZXMgd2l0aCB0aGUgTGFyZ2VzdCBOZWdhdGl2ZSBDaGFuZ2UgaW4gV29tZW4ncyBTYWZldHkgYW5kIFNlY3VyaXR5IGluIEFueSBHaXZlbiBZZWFyIiwNCiAgICAgICB4ID0gIlllYXIiLA0KICAgICAgIHkgPSAiV29tZW4ncyBTYWZ0ZXkgYW5kIFNlY3VyaXR5IFNjb3JlIikgKw0KICB0aGVtZV9saWdodCgpICsNCiAgZ2VvbV9saW5lKGRhdGEgPSBzdWJzZXQoZmlsdGVyZWRjaGFuZ2UsIGNvdW50cmllcyAlaW4lIGRlY19zc193b21lbiksIGFlcyhjb2xvciA9IGNvdW50cmllcyksIHNpemUgPSAxLjUsIGFscGhhID0gMC43KQ0KYGBgDQoNCmBgYHtyIHJlZ2lvbl9hdmVyYWdlfQ0KDQpkYXRhX2J5X3llYXIgJT4lDQogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSBhdmdfcGZfc3MsIGdyb3VwID0gcmVnaW9uKSkgKw0KICBnZW9tX2xpbmUoYWVzKGNvbG9yID0gcmVnaW9uKSwgc2l6ZSA9IDEuMjUsIGFscGhhID0gMC41KSArDQogIGxhYnModGl0bGUgPSAiQXZlcmFnZSBTYWZldHkgYW5kIFNlY3VyaXR5IGJ5IFJlZ2lvbiIsIHggPSAiWWVhciIsIHkgPSAiU2FmZXR5IGFuZCBTZWN1cml0eSBTY29yZSIsIGZpbGwgPSAiUmVnaW9uIikgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDYsMTAsMC41KSkgKw0KICB0aGVtZV9saWdodCgpIA0KDQoNCmRhdGFfYnlfeWVhciAlPiUNCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IGF2Z19wZl9zc193b21lbiwgZ3JvdXAgPSByZWdpb24pKSArDQogIGdlb21fbGluZShhZXMoY29sb3IgPSByZWdpb24pLCBzaXplID0gMS4yNSwgYWxwaGEgPSAwLjUpICsNCiAgbGFicyh0aXRsZSA9ICJBdmVyYWdlIFNhZmV0eSBhbmQgU2VjdXJpdHkgb2YgV29tZW4gYnkgUmVnaW9uIiwgeCA9ICJZZWFyIiwgeSA9ICJTYWZldHkgYW5kIFNlY3VyaXR5IFNjb3JlIiwgZmlsbCA9ICJSZWdpb24iKSArDQogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoNiwxMCwwLjUpKSArDQogIHRoZW1lX2xpZ2h0KCkNCmBgYA0KDQoNCmBgYHtyIGNvbXBhcmVfdmFyaWFibGVzfQ0KZGF0YV9ieV95ZWFyICU+JQ0KICBmaWx0ZXIoeWVhciA9PSAyMDE2LCByZWdpb24gJWluJSBjKCJOb3J0aCBBbWVyaWNhIiwgIldlc3Rlcm4gRXVyb3BlIiwgIkVhc3Rlcm4gRXVyb3BlIiwgIkxhdGluIEFtZXJpY2EgJiB0aGUgQ2FyaWJiZWFuIikpICU+JQ0KICBzZWxlY3QocmVnaW9uLCBhdmdfcGZfc3MsIGF2Z19wZl9zc193b21lbikgJT4lIG1lbHQgJT4lDQogIGdncGxvdChhZXMocmVnaW9uLCB2YWx1ZSwgZmlsbCA9IHZhcmlhYmxlKSkgKyBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSArDQogIGxhYnMoeCA9ICJSZWdpb24iLCB5ID0gIlNhZmV0eSBhbmQgU2VjdXJpdHkgU2NvcmUiLCB0aXRsZSA9ICIyMDE2IE92ZXJhbGwgYW5kIFdvbWVuJ3MgU2FmZXR5IGFuZCBTZWN1cml0eSBCeSBSZWdpb24gKFdlc3Rlcm4gSGVtaXNwaGVyZSkiLCBmaWxsID0gIlZhcmlhYmxlIikgKyBzY2FsZV9maWxsX21hbnVhbChsYWJlbHMgPSBjKCJBdmVyYWdlIE92ZXJhbGwgU2VjdXJpdHkiLCAiQXZlcmFnZSBXb21lbidzIFNlY3VyaXR5IiksIHZhbHVlcyA9IGMoIlJlZCIsICJCbHVlIikpDQoNCmRhdGFfYnlfeWVhciAlPiUNCiAgZmlsdGVyKHllYXIgPT0gMjAxNiwgcmVnaW9uICVpbiUgYygiU291dGggQXNpYSIsICJPY2VhbmlhIiwgIkVhc3QgQXNpYSIsICJDYXVjYXN1cyAmIENlbnRyYWwgQXNpYSIsICJNaWRkbGUgRWFzdCAmIE5vcnRoIEFmcmljYSIsICJTdWItU2FoYXJhbiBBZnJpY2EiKSkgJT4lDQogIHNlbGVjdChyZWdpb24sIGF2Z19wZl9zcywgYXZnX3BmX3NzX3dvbWVuKSAlPiUgbWVsdCAlPiUNCiAgZ2dwbG90KGFlcyhyZWdpb24sIHZhbHVlLCBmaWxsID0gdmFyaWFibGUpKSArIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJkb2RnZSIpICsNCiAgbGFicyh4ID0gIlJlZ2lvbiIsIHkgPSAiU2FmZXR5IGFuZCBTZWN1cml0eSBTY29yZSIsIHRpdGxlID0gIjIwMTYgT3ZlcmFsbCBhbmQgV29tZW4ncyBTYWZldHkgYW5kIFNlY3VyaXR5IEJ5IFJlZ2lvbiAoRWFzdGVybiBIZW1pc2hwZXJlKSIsIGZpbGwgPSAiVmFyaWFibGUiKSArIHNjYWxlX2ZpbGxfbWFudWFsKGxhYmVscyA9IGMoIkF2ZXJhZ2UgT3ZlcmFsbCBTZWN1cml0eSIsICJBdmVyYWdlIFdvbWVuJ3MgU2VjdXJpdHkiKSwgdmFsdWVzID0gYygiUmVkIiwgIkJsdWUiKSkNCg0KI3VuaXF1ZShkYXRhX2J5X3llYXIkcmVnaW9uKQ0KICANCmBgYA0KDQoNCg0KYGBge3IgcGZfdnNfZWZfdnNfd3N9DQpnZ3Bsb3QoZGF0YSA9IGhmaTE2LCBhZXMoeCA9IHBmX3Njb3JlLCB5ID0gZWZfc2NvcmUpKSArIA0KICBnZW9tX3BvaW50KGFlcyhjb2wgPSBwZl9zc193b21lbikpICsNCiAgbGFicyh4ID0gIlBlcnNvbmFsIEZyZWVkb20gU2NvcmUiLCB5ID0gIkVjb25vbWljIEZyZWVkb20gU2NvcmUiLCBtYWluID0gIlBlcnNvbmFsIGFuZCBFY29ub21pYyBGcmVlZG9tIGFuZCBXb21lbiBTZWN1cml0eSIsIGNvbG9yID0gIlNlY3VyaXR5IG9mIFdvbWVuIikNCmBgYA0KDQpgYGB7ciBjaGxvcm9wZXRoIG1hcCBvZiBIdW1hbiBmcmVlZG9tIHNjb3JlIDIwMTZ9DQojIGxpZ2h0IGdyZXkgYm91bmRhcmllcw0KbCA8LSBsaXN0KGNvbG9yID0gdG9SR0IoImdyZXkiKSwgd2lkdGggPSAwLjkpDQojIHNwZWNpZnkgbWFwIHByb2plY3Rpb24vb3B0aW9ucw0KZyA8LSBsaXN0KA0Kc2hvd2ZyYW1lID0gRkFMU0UsDQpzaG93Y29hc3RsaW5lcyA9IEZBTFNFLA0KcHJvamVjdGlvbiA9IGxpc3QodHlwZSA9ICdNZXJjYXRvcicpDQopDQoNCnBsb3RfZ2VvKHNjb3JlMTYpICU+JQ0KDQphZGRfdHJhY2UoDQp6ID0gfiByb3VuZChoZl9zY29yZSwgMiksIGNvbG9yID0gfmhmX3Njb3JlLCBjb2xvcnMgPSAnQmx1ZXMnLCANCnRleHQgPSB+Y291bnRyaWVzLCBsb2NhdGlvbnMgPSB+SVNPX2NvZGUsIG1hcmtlciA9IGxpc3QobGluZSA9IGwpKSAlPiUNCmNvbG9yYmFyKHRpdGxlID0gJ0h1bWFuIEZyZWVkb20gXG5TY29yZSwgMjAxNicpICU+JQ0KbGF5b3V0KA0KdGl0bGUgPSAnSHVtYW4gRnJlZWRvbSBTY29yZSwgMjAxNicsDQpnZW8gPSBnDQopDQpgYGANCg0KYGBge3IgY2hsb3JvcGV0aCBtYXAgb2YgSHVtYW4gZnJlZWRvbSBzY29yZSAyMDA4fQ0KbCA8LSBsaXN0KGNvbG9yID0gdG9SR0IoImdyZXkiKSwgd2lkdGggPSAwLjkpDQojIHNwZWNpZnkgbWFwIHByb2plY3Rpb24vb3B0aW9ucw0KZyA8LSBsaXN0KA0Kc2hvd2ZyYW1lID0gRkFMU0UsDQpzaG93Y29hc3RsaW5lcyA9IEZBTFNFLA0KcHJvamVjdGlvbiA9IGxpc3QodHlwZSA9ICdNZXJjYXRvcicpDQopDQoNCnBsb3RfZ2VvKHNjb3JlMDgpICU+JQ0KDQphZGRfdHJhY2UoDQp6ID0gfiByb3VuZChoZl9zY29yZSwgMiksIGNvbG9yID0gfmhmX3Njb3JlLCBjb2xvcnMgPSAnQmx1ZXMnLCANCnRleHQgPSB+Y291bnRyaWVzLCBsb2NhdGlvbnMgPSB+SVNPX2NvZGUsIG1hcmtlciA9IGxpc3QobGluZSA9IGwpKSAlPiUNCmNvbG9yYmFyKHRpdGxlID0gJ0h1bWFuIEZyZWVkb20gXG5TY29yZSwgMjAwOCcpICU+JQ0KbGF5b3V0KA0KdGl0bGUgPSAnSHVtYW4gRnJlZWRvbSBTY29yZSwgMjAwOCcsDQpnZW8gPSBnDQopDQpgYGANCg0KYGBge3IgfQ0KZ2dwbG90Y2hhbmdlIDwtIGdncGxvdChkYXRhID0gbWFwLndvcmxkLmNoYW5nZSwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cD0gZ3JvdXAsIGZpbGwgPSBodW1hbl9mcmVlZG9tX3Njb3JlLCB0ZXh0ID0gIHBhc3RlKCJjb3VudHJ5OiIsIHJlZ2lvbiwgIjxicj4iLCAicGVyc29uYWxfZnJlZWRvbV9zY29yZToiLCBwZXJzb25hbF9mcmVlZG9tX3Njb3JlLCAiPGJyPiIsICJwZXJzb25hbF9mcmVlZG9tX3Jhbms6IiwgcGVyc29uYWxfZnJlZWRvbV9yYW5rLCAiPGJyPiIsICJlY29ub215X2ZyZWVkb21fc2NvcmU6IiwgZWNvbm9teV9mcmVlZG9tX3Njb3JlLCAiPGJyPiIsICJlY29ub215X2ZyZWVkb21fcmFuazoiLCBlY29ub215X2ZyZWVkb21fcmFuaywgIjxicj4iLCAiaHVtYW5fZnJlZWRvbV9zY29yZToiLCBodW1hbl9mcmVlZG9tX3Njb3JlLCAiPGJyPiIsICJodW1hbl9mcmVlZG9tX3Jhbms6IiwgaHVtYW5fZnJlZWRvbV9yYW5rKSkpICsNCiAgZ2VvbV9wb2x5Z29uKCkgKw0KICBzY2FsZV9maWxsX2dyYWRpZW50Mihsb3cgPSAiIzM4M0M0NiIsIGhpZ2ggPSAiI0Q0REJFQSIsIG1pZD0iIzVBNzZBRiIsIG5hbWU9IkNoYW5nZSBvZiBcbkZyZWVkb20gU2NvcmUiKSArDQogIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSAgZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiZ3JleTUwIiksDQogICAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSAidG9wIiwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsNCiAgbGFicyh0aXRsZSA9ICJDaGFuZ2VzIGZyb20gMjAwOCB0byAyMDE2IikgIysNCiAgI2d1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKHRpdGxlPU5VTEwpKQ0KZ2dwbG90bHkoZ2dwbG90Y2hhbmdlLCB0b29sdGlwID0gYygidGV4dCIpKQ0KYGBgDQoNCg0KDQoNCg0KYGBge3Igd29ybGQgaHVtYW4gZnJlZWRvbSByYW5rIGluIDIwMTYgfQ0Kc3RyKHNjb3JlMTYpDQpwIDwtIGdncGxvdChzY29yZTE2LCBhZXMoeD1oZl9zY29yZSAseT1yZW9yZGVyKGNvdW50cmllcyxoZl9yYW5rKSkpICsgDQogIGdlb21fcG9pbnQoY29sb3VyID0gInJlZCIsIGFscGhhID0gLjUpICsgDQogIGdlb21fc2VnbWVudChhZXMoeWVuZD1yZW9yZGVyKGNvdW50cmllcyxoZl9yYW5rKSksIHhlbmQgPSAwLCBjb2xvdXI9InBpbmsiLCBhbHBoYSA9IC41KSArIA0KICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsIGhqdXN0ID0gMSkpICsgDQogIGxhYnModGl0bGUgPSAiV29ybGQgSHVtYW4gRnJlZWRvbSBSYW5rIGluIDIwMTYiLCB5ID0gIkNvdW50cnkgTmFtZSIsIHggPSAiSHVtYW4gRnJlZWRvbSBSYW5rIikNCmdncGxvdGx5KHApDQpgYGANCg0KDQpgYGB7ciAyMDE2IHdvbWVuIFBlcnNvbmFsIEZyZWVkb20gdnMgRWNvbm9taWMgRnJlZWRvbX0NCnNjb3JlID0gaGZpICU+JSBmaWx0ZXIoeWVhciA9PSAyMDE2KSAlPiUgc2VsZWN0KHBmX3NzX3dvbWVuLCBJU09fY29kZSwgY291bnRyaWVzLCByZWdpb24sIHBmX3Njb3JlLCBwZl9yYW5rLCBlZl9zY29yZSwgZWZfcmFuaywgaGZfc2NvcmUsIGhmX3JhbmspICU+JSAgbmEub21pdCgpDQpwMSA9Z2dwbG90KHNjb3JlLCBhZXMoeCA9IGVmX3Njb3JlLCB5ID0gcGZfc2NvcmUsIGNvbG9yID0gcmVnaW9uKSwgZ3JvdXAgPSBjb3VudHJpZXMpDQoNCnBvaW50c1RvTGFiZWwgPC0gYygiUnVzc2lhIiwgIlZlbmV6dWVsYSIsICJJcmFxIiwgIk15YW5tYXIiLCAiU3VkYW4iLA0KICAgICAgICAgICAgICAgICAgICJBZmdoYW5pc3RhbiIsICJDb25nbyIsICJHcmVlY2UiLCAiQXJnZW50aW5hIiwgIkJyYXppbCIsDQogICAgICAgICAgICAgICAgICAgIkluZGlhIiwgIkl0YWx5IiwgIkNoaW5hIiwgIlNvdXRoIEFmcmljYSIsICJTcGFpbiIsDQogICAgICAgICAgICAgICAgICAgIkJvdHN3YW5hIiwgIkNhcGUgVmVyZGUiLCAiQmh1dGFuIiwgIlJ3YW5kYSIsICJGcmFuY2UiLA0KICAgICAgICAgICAgICAgICAgICJVbml0ZWQgU3RhdGVzIiwgIkdlcm1hbnkiLCAiQnJpdGFpbiIsICJCYXJiYWRvcyIsICJOb3J3YXkiLCAiSmFwYW4iLA0KICAgICAgICAgICAgICAgICAgICJOZXcgWmVhbGFuZCIsICJTaW5nYXBvcmUiKQ0KbVIyIDwtIHN1bW1hcnkobG0ocGZfc2NvcmUgfiAxICsgZWZfc2NvcmUgLCBkYXRhID0gc2NvcmUpKSRyLnNxdWFyZWQNCm1SMiA8LSBwYXN0ZTAoZm9ybWF0KG1SMiwgZGlnaXRzID0gMikpDQoNCnAyID0gcDEgKyBnZW9tX3Ntb290aChtYXBwaW5nID0gYWVzKGxpbmV0eXBlID0gInIyIiksDQogICAgICAgICAgICAgIG1ldGhvZCA9ICJsbSIsc2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgY29sb3IgPSAicmVkIikgKyAjIGdlb21fcG9pbnQoc2l6ZSA9IDIsIHN0cm9rZSA9IDEuMjUpICsNCiAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IHJvdW5kKHBmX3NzX3dvbWVuKSksIGFscGhhID0gMC42KSsgbGFicyhzaXplID0gIldvbWVuIFNlY3VyaXR5IFNjb3JlIikgKyANCiAgZ2VvbV90ZXh0X3JlcGVsKGFlcyhsYWJlbCA9IGNvdW50cmllcykgLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAyLjUsIGRhdGEgPSBmaWx0ZXIoc2NvcmUsIGNvdW50cmllcyAlaW4lIHBvaW50c1RvTGFiZWwpLCBmb3JjZSA9IDIgKSArICNjaGVja19vdmVybGFwID0gVFJVRQ0KICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJFY29ub21pYyBGcmVlZG9tIFNjb3JlLCAyMDE2ICgxMCA9IE1vc3QgRnJlZSkiLCBsaW1pdHMgPSBjKDIuNSw5LjUpLCBicmVha3MgPSAyLjU6OS41KSArDQogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gIlBlcnNvbmFsIEZyZWVkb20gU2NvcmUsIDIwMTYgKDEwID0gTW9zdCBGcmVlKSIsIGxpbWl0cyA9IGMoMi41LDkuNSksIGJyZWFrcyA9IDIuNTo5LjUpICsNCiAgc2NhbGVfY29sb3JfYnJld2VyKG5hbWUgPSAiIiAsIHR5cGUgPSAnZGl2JywgcGFsZXR0ZSA9ICdTcGVjdHJhbCcpICsNCiAgc2NhbGVfbGluZXR5cGUobmFtZSA9ICIiLA0KICAgICAgICAgICAgICAgICBicmVha3MgPSAicjIiLA0KICAgICAgICAgICAgICAgICBsYWJlbHMgPSBsaXN0KGJxdW90ZShSXjI9PS4obVIyKSkpLA0KICAgICAgICAgICAgICAgICBndWlkZSA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGxpbmV0eXBlID0gMSwgc2l6ZSA9IDIsIGNvbG9yID0gInJlZCIpLCBvcmRlcj0yKSkgKw0KICBnZ3RpdGxlKCJFY29ub21pYyAmIFBlcnNvbmFsIEZyZWVkb20gYW5kIFdvbWVuIFNlY3VyaXR5IDIwMTYiKSArDQogIHRoZW1lX21pbmltYWwoKSArICMgc3RhcnQgd2l0aCBhIG1pbmltYWwgdGhlbWUgYW5kIGFkZCB3aGF0IHdlIG5lZWQNCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJncmF5MjAiKSwNCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvciA9ICJncmF5MTAiKSwNCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KGZhY2UgPSAiaXRhbGljIiksDQogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dCh2anVzdCA9IC0xKSwgIyBtb3ZlIHRpdGxlIGF3YXkgZnJvbSBheGlzDQogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dCh2anVzdCA9IDIpLCAjIG1vdmUgYXdheSBmb3IgYXhpcw0KICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksICMgZWxlbWVudF9ibGFuaygpIGlzIGhvdyB3ZSByZW1vdmUgZWxlbWVudHMNCiAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG9yID0gImdyYXk0MCIsIHNpemUgPSAwLjMpLA0KICAgICAgICAjcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKQ0KICAgICAgICAjYXhpcy5saW5lLnkgPSBlbGVtZW50X2JsYW5rKCkNCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfbGluZShjb2xvciA9ICJncmF5Iiwgc2l6ZSA9IDAuMikNCiAgICAgICAgI3BhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfYmxhbmsoKQ0KICAgICAgICApDQogIA0KDQpzdXBwcmVzc1dhcm5pbmdzKHByaW50KHAyKSkNCmBgYA0KDQoNCmBgYHtyIDIwMDggcGVyc29uYWwgZnJlZWRvbX0NCmRmID0gaGZpICU+JSBmaWx0ZXIoeWVhciA9PSAyMDA4KSAlPiUgc2VsZWN0KHllYXIsIElTT19jb2RlLCBjb3VudHJpZXMsIHJlZ2lvbiwgc3RhcnRzX3dpdGgoJ3BmXycpKQ0KDQpkZj1kZlssY29sU3Vtcyhpcy5uYShkZikpPG5yb3coZGYpXQ0KDQpkZiA9IGRmICU+JSBuYS5vbWl0KCkNCmNvcm1hdCA8LSByb3VuZChjb3IoZGZbLDU6NTddKSwyKQ0KDQojDQpnZXRfbG93ZXJfdHJpPC1mdW5jdGlvbihjb3JtYXQpew0KICBjb3JtYXRbdXBwZXIudHJpKGNvcm1hdCldIDwtIE5BDQogIHJldHVybihjb3JtYXQpDQp9DQpnZXRfdXBwZXJfdHJpIDwtIGZ1bmN0aW9uKGNvcm1hdCl7DQogIGNvcm1hdFtsb3dlci50cmkoY29ybWF0KV08LSBOQQ0KICByZXR1cm4oY29ybWF0KQ0KfQ0KDQpyZW9yZGVyX2Nvcm1hdCA8LSBmdW5jdGlvbihjb3JtYXQpew0KICAjIFVzZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHZhcmlhYmxlcyBhcyBkaXN0YW5jZQ0KICBkZCA8LSBhcy5kaXN0KCgxLWNvcm1hdCkvMikgDQogIGhjIDwtIGhjbHVzdChkZCkNCiAgY29ybWF0IDwtY29ybWF0W2hjJG9yZGVyLCBoYyRvcmRlcl0NCn0NCmBgYA0KDQpgYGB7ciBjb3JyZWxhdGlvbiBIZWF0bWFwfQ0KY29ybWF0IDwtIHJlb3JkZXJfY29ybWF0KGNvcm1hdCkNCnVwcGVyX3RyaSA8LSBnZXRfdXBwZXJfdHJpKGNvcm1hdCkNCiMgTWVsdCB0aGUgY29ycmVsYXRpb24gbWF0cml4DQptZWx0ZWRfY29ybWF0IDwtIG1lbHQodXBwZXJfdHJpLCBuYS5ybSA9IFRSVUUpDQojIENyZWF0ZSBhIGdnaGVhdG1hcA0KZ2doZWF0bWFwIDwtIGdncGxvdChtZWx0ZWRfY29ybWF0LCBhZXMoVmFyMiwgVmFyMSwgZmlsbCA9IHZhbHVlKSkrDQogIGdlb21fdGlsZShjb2xvciA9ICJ3aGl0ZSIpKw0KICBzY2FsZV9maWxsX2dyYWRpZW50Mihsb3cgPSAiYmx1ZSIsIGhpZ2ggPSAicmVkIiwgbWlkID0gIndoaXRlIiwgDQogICAgICAgICAgICAgICAgICAgICAgIG1pZHBvaW50ID0gMCwgbGltaXQgPSBjKC0xLDEpLCBzcGFjZSA9ICJMYWIiLCANCiAgICAgICAgICAgICAgICAgICAgICAgbmFtZT0iUGVhcnNvblxuQ29ycmVsYXRpb24iKSArDQogIHRoZW1lX21pbmltYWwoKSsgIyBtaW5pbWFsIHRoZW1lDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIHZqdXN0ID0gMSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSA4LjUsIGhqdXN0ID0gMSksIA0KICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG9yID0gImdyYXkiLCBzaXplID0gMC4yKSkgKw0KICBjb29yZF9maXhlZCgpDQoNCmdnaGVhdG1hcCArIA0KICB0aGVtZSgNCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksDQogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLA0KICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheSIsIHNpemUgPSAwLjIpLA0KICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLA0KICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCkNCiAgICApICsgZ2d0aXRsZSgiUGVyc29uYWwgRnJlZWRvbSwgMjAwOCIpDQoNCmBgYA0KDQoNCg0KYGBge3Iga21lYW5zX2FuYWx5c2lzfQ0KaGZpMTYgPSBoZmlbaGZpJHllYXIgPT0gMjAxNixdDQpoZmkxNiA8LSBoZmkxNiAlPiUgc2VsZWN0KHllYXIsIFgxID0gY291bnRyaWVzLCByZWdpb24sIHBmX3NzLCBwZl9yb2wsIHBmX3JlbGlnaW9uLCBwZl9hc3NvY2lhdGlvbiwgcGZfaWRlbnRpdHksIHBmX2V4cHJlc3Npb24sIHBmX3Njb3JlLCBwZl9tb3ZlbWVudCwgZWZfZ292ZXJubWVudCwgZWZfbGVnYWwsIGVmX3Njb3JlLCBlZl9yZWd1bGF0aW9uLCBlZl9tb25leSwgZWZfdHJhZGUsIGNvbnRhaW5zKCJ3b21lbiIpLCBwZl9pZGVudGl0eV9zZXhfZmVtYWxlLCBwZl9pZGVudGl0eV9kaXZvcmNlKQ0KaGZpMTYgPC0gaGZpMTZbLXdoaWNoKGlzLm5hKGhmaTE2WzQ6MjZdKSksXSAlPiUgbmEub21pdCgpDQpzZXQuc2VlZCgxMjM1KSANCmNsdXN0ZXJzIDwtIGhmaTE2ICU+JSBzZWxlY3QoY29udGFpbnMoIndvbWVuIikpICU+JSBuYS5vbWl0KCkNCmszIDwtIGttZWFucyhjbHVzdGVycywgMykNCmszDQpmdml6X2NsdXN0ZXIoazMsIGRhdGEgPSBjbHVzdGVycykNCmZ2aXpfbmJjbHVzdChjbHVzdGVycywga21lYW5zLCBtZXRob2QgPSAid3NzIikNCmhmaTE2JGNsdXN0ZXJzIDwtIGFzLmZhY3RvcihrMyRjbHVzdGVyKQ0KaGZpMTYkcmVnaW9uZiA8LSBmYWN0b3IoaGZpMTYkcmVnaW9uKQ0KYGBgDQoNCmBgYHtyIGNvcnJwbG90fQ0KY29yciA8LSByb3VuZChjb3IobmEub21pdChoZmkxNls0OjI2XSkpLCAxKQ0KZ2djb3JycGxvdChjb3JyLCBoYy5vcmRlciA9IFRSVUUsIG1ldGhvZCA9ICJjaXJjbGUiLCBsYWIgPSBUUlVFLCBsYWJfc2l6ZSA9IDMpDQpgYGANCg0KYGBge3J9DQpoZmkxNiA8LSBoZmkxNiAlPiUNCiAgZ3JvdXBfYnkoY2x1c3RlcnMpICU+JQ0KICBtdXRhdGUoY2x1c3RlcmF2Z3dzcyA9IG1lYW4ocGZfc3Nfd29tZW4pLCBjbHVzdGVyc2R3c3MgPSBzZChwZl9zc193b21lbiksIGNsdXN0ZXJhdmdzcyA9IG1lYW4ocGZfc3MpLCBjbHVzdGVyc2RzcyA9IHNkKHBmX3NzKSkNCmBgYA0KDQpgYGB7ciB3c192c19yZWxpZ2lvbn0NCmdncGxvdChkYXRhID0gaGZpMTYsIGFlcyh5ID0gcGZfc3Nfd29tZW4sIHggPSBwZl9yZWxpZ2lvbikpICsNCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IDE6bmxldmVscyhoZmkxNiRyZWdpb25mKSkgKw0KICBnZW9tX2ppdHRlcihhZXMoY29sb3IgPSBjbHVzdGVycywgc2hhcGUgPSByZWdpb25mKSkgKw0KICBsYWJzKGNvbCA9ICJDbHVzdGVycyIsDQogICAgICAgc2hhcGUgPSAiUmVnaW9ucyIsDQogICAgICAgeCA9ICJSZWxpZ2lvdXMgRnJlZWRvbSIsDQogICAgICAgeSA9ICJTZWN1cml0eSBvZiBXb21lbiIpICsNCiAgZ2VvbV90ZXh0X3JlcGVsKA0KICAgIGRhdGEgPSBzdWJzZXQoaGZpMTYsIHBmX3NzX3dvbWVuICA8IChjbHVzdGVyYXZnd3NzIC0gY2x1c3RlcnNkd3NzKSksDQogICAgYWVzKA0KICAgICAgeCA9IHBmX3JlbGlnaW9uLA0KICAgICAgeSA9IHBmX3NzX3dvbWVuLA0KICAgICAgbGFiZWwgPSBYMSwNCiAgICAgIGNvbG9yID0NCiAgICAgICAgY2x1c3RlcnMNCiAgICApLA0KICAgIG51ZGdlX3kgPSAuNQ0KICApDQpgYGANCg0KYGBge3Igd3NfdnNfcm9sfQ0KZ2dwbG90KGRhdGEgPSBoZmkxNiwgYWVzKHkgPSBwZl9zc193b21lbiwgeCA9IHBmX3JvbCkpICsNCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IDE6bmxldmVscyhoZmkxNiRyZWdpb25mKSkgKw0KICBnZW9tX2ppdHRlcihhZXMoY29sb3IgPSBjbHVzdGVycywgc2hhcGUgPSByZWdpb25mKSkgKw0KICBsYWJzKGNvbCA9ICJDbHVzdGVycyIsDQogICAgICAgc2hhcGUgPSAiUmVnaW9ucyIsDQogICAgICAgeCA9ICJSdWxlIG9mIExhdyIsDQogICAgICAgeSA9ICJTZWN1cml0eSBvZiBXb21lbiIpICsNCiAgZ2VvbV90ZXh0X3JlcGVsKA0KICAgIGRhdGEgPSBzdWJzZXQoaGZpMTYsIHBmX3NzX3dvbWVuICA8IChjbHVzdGVyYXZnd3NzIC0gY2x1c3RlcnNkd3NzKSksDQogICAgYWVzKA0KICAgICAgeCA9IHBmX3JvbCwNCiAgICAgIHkgPSBwZl9zc193b21lbiwNCiAgICAgIGxhYmVsID0gWDEsDQogICAgICBjb2xvciA9DQogICAgICAgIGNsdXN0ZXJzDQogICAgKSwNCiAgICBudWRnZV95ID0gLjUNCiAgKQ0KYGBgDQoNCmBgYHtyIHdzX3ZzX2Vmc2NvcmV9DQpnZ3Bsb3QoZGF0YSA9IGhmaTE2LCBhZXMoeSA9IHBmX3NzX3dvbWVuLCB4ID0gZWZfc2NvcmUpKSArDQogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSAxOm5sZXZlbHMoaGZpMTYkcmVnaW9uZikpICsNCiAgZ2VvbV9qaXR0ZXIoYWVzKGNvbG9yID0gY2x1c3RlcnMsIHNoYXBlID0gcmVnaW9uZikpICsNCiAgbGFicyhjb2wgPSAiQ2x1c3RlcnMiLA0KICAgICAgIHNoYXBlID0gIlJlZ2lvbnMiLA0KICAgICAgIHggPSAiRWNvbm9taWMgRnJlZWRvbSBTY29yZSIsDQogICAgICAgeSA9ICJTZWN1cml0eSBvZiBXb21lbiIpICsNCiAgZ2VvbV90ZXh0X3JlcGVsKA0KICAgIGRhdGEgPSBzdWJzZXQoaGZpMTYsIHBmX3NzX3dvbWVuICA8IChjbHVzdGVyYXZnd3NzIC0gY2x1c3RlcnNkd3NzKSksDQogICAgYWVzKA0KICAgICAgeCA9IGVmX3Njb3JlLA0KICAgICAgeSA9IHBmX3NzX3dvbWVuLA0KICAgICAgbGFiZWwgPSBYMSwNCiAgICAgIGNvbG9yID0NCiAgICAgICAgY2x1c3RlcnMNCiAgICApLA0KICAgIG51ZGdlX3kgPSAuNQ0KICApDQpgYGANCg0KYGBge3Igd3NfdnNfZWZtb25leX0NCmdncGxvdChkYXRhID0gaGZpMTYsIGFlcyh5ID0gcGZfc3Nfd29tZW4sIHggPSBlZl9tb25leSkpICsNCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IDE6bmxldmVscyhoZmkxNiRyZWdpb25mKSkgKw0KICBnZW9tX2ppdHRlcihhZXMoY29sb3IgPSBjbHVzdGVycywgc2hhcGUgPSByZWdpb25mKSkgKw0KICBsYWJzKGNvbCA9ICJDbHVzdGVycyIsDQogICAgICAgc2hhcGUgPSAiUmVnaW9ucyIsDQogICAgICAgeCA9ICJBY2Nlc3MgdG8gU291bmQgTW9uZXkiLA0KICAgICAgIHkgPSAiU2VjdXJpdHkgb2YgV29tZW4iKSArDQogIGdlb21fdGV4dF9yZXBlbCgNCiAgICBkYXRhID0gc3Vic2V0KGhmaTE2LCBwZl9zc193b21lbiAgPCAoY2x1c3RlcmF2Z3dzcyAtIGNsdXN0ZXJzZHdzcykpLA0KICAgIGFlcygNCiAgICAgIHggPSBlZl9tb25leSwNCiAgICAgIHkgPSBwZl9zc193b21lbiwNCiAgICAgIGxhYmVsID0gWDEsDQogICAgICBjb2xvciA9DQogICAgICAgIGNsdXN0ZXJzDQogICAgKSwNCiAgICBudWRnZV95ID0gLjUNCiAgKQ0KYGBgDQoNCmBgYHtyIHdzX3ZzX3BmaWRlbnRpdHl9DQpnZ3Bsb3QoZGF0YSA9IGhmaTE2LCBhZXMoeSA9IHBmX3NzX3dvbWVuLCB4ID0gcGZfaWRlbnRpdHkpKSArDQogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSAxOm5sZXZlbHMoaGZpMTYkcmVnaW9uZikpICsNCiAgZ2VvbV9qaXR0ZXIoYWVzKGNvbG9yID0gY2x1c3RlcnMsIHNoYXBlID0gcmVnaW9uZikpICsNCiAgbGFicyhjb2wgPSAiQ2x1c3RlcnMiLA0KICAgICAgIHNoYXBlID0gIlJlZ2lvbnMiLA0KICAgICAgIHggPSAiQWNjZXNzIHRvIERpdm9yY2UiLA0KICAgICAgIHkgPSAiU2VjdXJpdHkgb2YgV29tZW4iKSArDQogIGdlb21fdGV4dF9yZXBlbCgNCiAgICBkYXRhID0gc3Vic2V0KGhmaTE2LCBwZl9zc193b21lbiAgPCAoY2x1c3RlcmF2Z3dzcyAtIGNsdXN0ZXJzZHdzcykpLA0KICAgIGFlcygNCiAgICAgIHggPSBwZl9pZGVudGl0eSwNCiAgICAgIHkgPSBwZl9zc193b21lbiwNCiAgICAgIGxhYmVsID0gWDEsDQogICAgICBjb2xvciA9DQogICAgICAgIGNsdXN0ZXJzDQogICAgKSwgbnVkZ2VfeSA9IC41DQogICkNCmBgYA0KDQpgYGB7ciB3c192c19wZnNjb3JlfQ0KZ2dwbG90KGRhdGEgPSBoZmkxNiwgYWVzKHkgPSBwZl9zc193b21lbiwgeCA9IHBmX3Njb3JlKSkgKw0KICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gMTpubGV2ZWxzKGhmaTE2JHJlZ2lvbmYpKSArDQogIGdlb21faml0dGVyKGFlcyhjb2xvciA9IGNsdXN0ZXJzLCBzaGFwZSA9IHJlZ2lvbmYpKSArDQogIGxhYnMoY29sID0gIkNsdXN0ZXJzIiwNCiAgICAgICBzaGFwZSA9ICJSZWdpb25zIiwNCiAgICAgICB4ID0gIlBlcnNvbmFsIEZyZWVkb20gU2NvcmUiLA0KICAgICAgIHkgPSAiU2VjdXJpdHkgb2YgV29tZW4iKSArDQogIGdlb21fdGV4dF9yZXBlbCgNCiAgICBkYXRhID0gc3Vic2V0KGhmaTE2LCBwZl9zc193b21lbiAgPCAoY2x1c3RlcmF2Z3dzcyAtIGNsdXN0ZXJzZHdzcykpLA0KICAgIGFlcygNCiAgICAgIHggPSBwZl9zY29yZSwNCiAgICAgIHkgPSBwZl9zc193b21lbiwNCiAgICAgIGxhYmVsID0gWDEsDQogICAgICBjb2xvciA9DQogICAgICAgIGNsdXN0ZXJzDQogICAgKSwgbnVkZ2VfeSA9IC41DQogICkNCmBgYA0KDQpgYGB7ciB3c192c19nZW5lcmFsX3NlY3VyaXR5fQ0KZ2dwbG90KGRhdGEgPSBoZmkxNiwgYWVzKHkgPSBwZl9zc193b21lbiwgeCA9IHBmX3NzKSkgKw0KICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gMTpubGV2ZWxzKGhmaTE2JHJlZ2lvbmYpKSArDQogIGdlb21faml0dGVyKGFlcyhjb2xvciA9IGNsdXN0ZXJzLCBzaGFwZSA9IHJlZ2lvbmYpKSArDQogIGxhYnMoY29sID0gIkNsdXN0ZXJzIiwNCiAgICAgICBzaGFwZSA9ICJSZWdpb25zIiwNCiAgICAgICB4ID0gIkdlbmVyYWwgU2VjdXJpdHkiLA0KICAgICAgIHkgPSAiU2VjdXJpdHkgb2YgV29tZW4iKSArDQogIGdlb21fdGV4dF9yZXBlbCgNCiAgICBkYXRhID0gc3Vic2V0KGhmaTE2LCBwZl9zcyAgPCAoY2x1c3RlcmF2Z3NzIC0gY2x1c3RlcnNkc3MpKSwNCiAgICBhZXMoDQogICAgICB4ID0gcGZfc3MsDQogICAgICB5ID0gcGZfc3Nfd29tZW4sDQogICAgICBsYWJlbCA9IFgxLA0KICAgICAgY29sb3IgPQ0KICAgICAgICBjbHVzdGVycw0KICAgICksIG51ZGdlX3kgPSAuNQ0KICApDQpgYGANCg0KYGBge3J9DQpwZXJjIDwtIGhmaTE2ICU+JSBncm91cF9ieShjbHVzdGVycykgJT4lIG11dGF0ZShuaW5jbHVzdCA9IG4oKSkgJT4lIHVuZ3JvdXAoKQ0KcGVyYyA8LSBwZXJjICU+JSBncm91cF9ieShyZWdpb24pICU+JSBtdXRhdGUobmlucmVnaW9uID0gbigpKSAlPiUgdW5ncm91cCgpDQpgYGANCg0KYGBge3IgY291bnRyaWVzIGFuZCB0aGVpciBjbHVzdGVyc30NCmhmaTE2ICU+JSANCiAgc2VsZWN0KFgxLGNsdXN0ZXJzKQ0KDQojIGxpZ2h0IGdyZXkgYm91bmRhcmllcw0KbCA8LSBsaXN0KGNvbG9yID0gY2x1c3RlcnMsIHdpZHRoID0gMC41KQ0KDQojIHNwZWNpZnkgbWFwIHByb2plY3Rpb24vb3B0aW9ucw0KZyA8LSBsaXN0KA0Kc2hvd2ZyYW1lID0gVFJVRSwNCnNob3djb2FzdGxpbmVzID0gVFJVRSwNCnNjb3BlPSJ3b3JsZCIsDQpwcm9qZWN0aW9uID0gbGlzdCh0eXBlID0gJ01lcmNhdG9yJykNCikNCmBgYA0KDQoNCmBgYHtyIGNsdXN0ZXJzIG9uIHdvcmxkIG1hcH0NCmhmaTE2JGNsdXN0ZXJzIDwtIGFzLmZhY3RvcihoZmkxNiRjbHVzdGVycykNCnBsb3RfZ2VvKGhmaTE2KSAlPiUNCmFkZF90cmFjZSh6ID0gfmNsdXN0ZXJzLA0KdGV4dCA9IH5YMSwgbG9jYXRpb25zID0gfklTT19jb2RlLCBtYXJrZXIgPSBsaXN0KGxpbmUgPSBsLGluaGVyaXQgPSBUUlVFKQ0KKSAlPiUNCmNvbG9yYmFyKHRpdGxlPSIiKSAlPiUgDQpsYXlvdXQoDQp0aXRsZSA9ICdXb21lbiBGcmVlZG9tIENsdXN0ZXJzIFdvcmxkIE1hcCcsDQpnZW8gPSBnDQopDQpgYGANCg0KDQoNCg0KDQoNCg==